package container

import (
	"encoding/json"
	"fmt"
	"github.com/sirupsen/logrus"
	"math/rand"
	"mydocker/common"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

type ContainerInfo struct {
	Pid         string   `json:"pid,omitempty"`         // 容器的 Init 进程在宿主机上的 PID
	ID          string   `json:"id,omitempty"`          // 容器 ID
	Name        string   `json:"name,omitempty"`        // 容器名
	Command     string   `json:"command,omitempty"`     // 容器内 Init 进程的运行命令
	CreateTime  string   `json:"createTime,omitempty"`  // 创建时间
	Status      string   `json:"status,omitempty"`      // 容器的状态
	Volume      string   `json:"volume,omitempty"`      // 容器挂载的数据卷
	NetworkName string   `json:"networkName,omitempty"` // 容器所在的网络
	IP          string   `json:"ip,omitempty"`
	PortMapping []string `json:"portMapping,omitempty"` // 端口映射
}

// RecordContainerInfo 记录容器信息到 config 文件中
func RecordContainerInfo(containerPID int, cmdArray []string, containerName, containerID, volume, networkName, ip string, ports []string) (*ContainerInfo, error) {
	// 如果未指定容器名，则使用随机生成的 containerID
	if containerName == "" {
		containerName = containerID
	}
	info := &ContainerInfo{
		Pid:         strconv.Itoa(containerPID),
		ID:          containerID,
		Name:        containerName,
		Command:     strings.Join(cmdArray, " "),
		CreateTime:  time.Now().Format("2006-01-02 15:04:05"),
		Status:      common.Running,
		Volume:      volume,
		NetworkName: networkName,
		IP:          ip,
		PortMapping: ports,
	}

	jsonBytes, err := json.Marshal(info)
	if err != nil {
		logrus.Errorf("conatiner info marshal failed: %v", err)
		return info, err
	}
	dirPath := path.Join(common.DefaultContainerInfoPath, containerID)
	if _, err = os.Stat(dirPath); err != nil && os.IsNotExist(err) {
		if err = os.MkdirAll(dirPath, common.Perm0622); err != nil {
			logrus.Errorf("mkdir container dir: %s, err: %v", dirPath, err)
			return info, err
		}
	}

	// 将容器信息写入文件
	fileName := path.Join(dirPath, common.ConfigName)
	file, err := os.Create(fileName)
	if err != nil {
		logrus.Errorf("create config.json, fileName: %s, err: %v", fileName, err)
		return info, err
	}
	defer file.Close()
	if _, err = file.WriteString(string(jsonBytes)); err != nil {
		logrus.Errorf("write config.json, fileName: %s, err: %v", fileName, err)
		return info, err
	}

	return info, nil
}

// GenerateContainerID 获取容器 ID（随机生成）
func GenerateContainerID() string {
	return randStringBytes(common.IDLength)
}

func randStringBytes(n int) string {
	letterBytes := "0123456789"
	newRand := rand.New(rand.NewSource(time.Now().UnixNano()))
	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[newRand.Intn(len(letterBytes))] // rand.Intn()返回一个取值范围在 [0,n) 的伪随机 int 值
	}
	return string(b)
}

// DeleteContainerInfo 删除记录容器信息的 config 文件
func DeleteContainerInfo(containerID string) error {
	dir := path.Join(common.DefaultContainerInfoPath, containerID)
	if err := os.RemoveAll(dir); err != nil {
		logrus.Errorf("remove container info, err: %v", err)
		return err
	}
	return nil
}

// GetLogFile 根据容器 ID 构建日志文件名
func GetLogFile(containerID string) string {
	return fmt.Sprintf(common.LogFile, containerID)
}
